package com.xydtech.ecard.ftp.service.impl;

import com.xydtech.common.utils.DateUtils;
import com.xydtech.ecard.ftp.domain.*;
import com.xydtech.ecard.ftp.enums.*;
import com.xydtech.ecard.ftp.mapper.FtpDepositLoanRateConfigMapper;
import com.xydtech.ecard.ftp.service.IFtpAverageCapitalPlusInterestService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: liliya
 * @Description: 还款方式:等额本息/等额本金
 * @Date: Created in 2023/8/30 18:16
 * @Modified:
 */
@Service
public class FtpAverageCapitalPlusInterestServiceImpl implements IFtpAverageCapitalPlusInterestService {

    private final Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    private FtpDepositLoanRateConfigMapper ftpDepositLoanRateConfigMapper;

    /**
     * 计算基础价格
     * @param ecardApiFtpInfo
     * @return
     */
    @Override
    public EcardFtpAverageCapitalPlusInterestSummaryBO getCalculateBasicPrice(EcardApiFtpInfo ecardApiFtpInfo) {

        EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO = new EcardFtpAverageCapitalPlusInterestSummaryBO();
        //等额本息/本金汇总:业务品种(贷款:1,定期存款2,个人活期3,单位活期4)(方法中默认1)
        //Integer ftpBusinessVariety = 1;
        Integer ftpBusinessVariety = ecardApiFtpInfo.getFtpBusinessVariety();
        summaryBO.setFtpBusinessVariety(ftpBusinessVariety);

        //还款方式(存款不填此项)(到期还本付息1,到期还本定期结息2,等额本金3,等额本息4,按还款计划还款5)
        //Integer loanRepaymentModeType = 3;
        Integer loanRepaymentModeType = ecardApiFtpInfo.getLoanRepaymentModeType();
        summaryBO.setLoanRepaymentModeType(loanRepaymentModeType);

        //等额本息/本金汇总:业务起始日
        //String dateStrInit = "2024-02-29";
        String dateStrInit = DateUtils.parseDateToStr("yyyy-MM-dd",ecardApiFtpInfo.getBeginDate());
        LocalDate localDateInit = LocalDate.parse(dateStrInit, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        summaryBO.setCashFlowStartDate(dateStrInit);
        summaryBO.setBusinessBeginDate(dateStrInit);
        summaryBO.setPricingBeginDate(dateStrInit);
        //等额本息/本金汇总:业务到期日
        //String dateStrFinally = "2024-05-29";
        String dateStrFinally = DateUtils.parseDateToStr("yyyy-MM-dd",ecardApiFtpInfo.getEndDate());
        summaryBO.setCashFlowMaturityDate(dateStrFinally);
        summaryBO.setBusinessEndDate(dateStrFinally);
        //等额本息/本金汇总:业务金额/本金
        //BigDecimal businessAmount = new BigDecimal("100000");
        BigDecimal businessAmount = ecardApiFtpInfo.getBusinessAmount();
        summaryBO.setPrincipal(businessAmount);
        //等额本息/本金汇总:对客利率(年利率)(等额本金无利率,不用修改)
        //String customerRateStr = "0.06";
        BigDecimal customerRate =ecardApiFtpInfo.getCustomerRate();
        //重定价频率(月)(3,6,12)(当利率类型为固定时:不使用重定价频率)
        //Integer repricingFrequencyType = 3;
        Integer repricingFrequencyType = ecardApiFtpInfo.getRepricingFrequencyType();
        summaryBO.setRepricingFrequencyType(repricingFrequencyType);
        //等额本息/本金汇总:还款频率(1,3,6,12)(只选1和3)
        //Integer repaymentFrequency = 3;
        Integer repaymentFrequency = ecardApiFtpInfo.getRepaymentFrequencyType();
        summaryBO.setRepaymentFrequency(repaymentFrequency);
        //等额本息/本金汇总:利率类型(固定:1,浮动:2)
        //Integer interestRateType = 2;
        Integer interestRateType = ecardApiFtpInfo.getInterestRateType();
        summaryBO.setInterestRateType(interestRateType);
        //等额本息/本金汇总:结息频率(月)(1,3)(暂无用)
        //Integer interestFrequencyType = 1;
        Integer interestFrequencyType = ecardApiFtpInfo.getInterestFrequencyType();
        summaryBO.setInterestFrequencyType(interestFrequencyType);
        //计算起始日和到期日的相差整月数(不足一月的不舍去!)
        int differenceInitMonth = DateUtils.getDifMonths(DateUtils.parseDateForDate(dateStrInit),DateUtils.parseDateForDate(dateStrFinally));
        //期数:实际金额数据循环条数
        int actualLimitTime = differenceInitMonth/repaymentFrequency;
        //期数:非实际金额数据循环条数
        int limitTime = 0;
        //等额本息/本金汇总:重定价到期日
        String dateStrRepricing = null;
        //利率类型:固定
        if(interestRateType == FtpInterestRateTypeEnum.FIXED_RATE.getValue()){
            dateStrRepricing = dateStrFinally;
            limitTime = actualLimitTime;
        }
        //利率类型:浮动
        else if(interestRateType == FtpInterestRateTypeEnum.FLOAT_RATE.getValue()){
            limitTime = repricingFrequencyType/repaymentFrequency;
            LocalDate localDateRepricing = localDateInit.plusMonths(repricingFrequencyType);
            localDateRepricing = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateRepricing);
            dateStrRepricing = localDateRepricing.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
        summaryBO.setRepricingDueDate(dateStrRepricing);
        //等额本息/本金汇总:还款次数
        summaryBO.setRepaymentTimes(actualLimitTime);
        //等额本息/本金汇总:计算实际相关字段的总条数
        summaryBO.setActualTotalNum(actualLimitTime);
        //计算非实际相关字段的总条数
        summaryBO.setTotalNum(limitTime);
        //等额本息:计算利率的次方值
        summaryBO.setActualPowNum(differenceInitMonth/repaymentFrequency);
        //等额本息/本金汇总:基础价格
        summaryBO.setBasicPrice(new BigDecimal(0));
        //等额本息/本金汇总:余额累计汇总值(初始化)
        summaryBO.setBalanceAccumulation(new BigDecimal(0));
        //等额本息/本金汇总:现金流*期限(求和)(初始化)
        summaryBO.setCalculateVal01(new BigDecimal(0));
        //等额本息/本金汇总:现金流*期限*利率(求和)(初始化)
        summaryBO.setCalculateVal02(new BigDecimal(0));

        /**
         * 初始化收益率曲线转置数据
         */
        Map<String,FtpDepositLoanRateDetailBO> ftpDepositLoanRateDetailBOMap = dateInitFtpDepositLoanRateData(summaryBO);

        //组装数据集合对象
        List<EcardFtpAverageCapitalPlusInterestBO> boList = new ArrayList<>();

        /**
         * 第1步
         * 初始化基本信息
         */
        calculateInitActualBasicInfo(summaryBO,boList);
        /**
         * 第2步
         * 计算业务日期及其实际日期间隔等
         */
        calculateBusinessDateInfo(summaryBO,boList);
        //处理小于整月的情况
        actualLimitTime = summaryBO.getActualTotalNum();
        if(actualLimitTime == boList.size()){
            actualLimitTime = actualLimitTime - 1;
            //等额本息/本金汇总:还款次数
            summaryBO.setRepaymentTimes(actualLimitTime);
            //等额本息/本金汇总:计算实际相关字段的总条数
            summaryBO.setActualTotalNum(actualLimitTime);
            //利率类型:固定
            if(interestRateType == 1){
                //计算非实际相关字段的总条数
                summaryBO.setTotalNum(actualLimitTime);
            }
        }
        /**
         * 第3步
         * 计算定价日期及其日期间隔等
         */
        calculateRepricingDateInfo(summaryBO,boList);

        //等额本息汇总:每期还款额(等额本金:还款额)
        BigDecimal repaymentAmount;
        //等额本息
        if(loanRepaymentModeType == FtpLoanRepaymentModeTypeEnum.LOAN_REPAYMENT_MODE4.getValue()){
            customerRate = customerRate.divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP);
            summaryBO.setRate(customerRate);
            //等额本息汇总:每期还款额
            //=ROUND(	((本金*利率/12)*((1+利率/12)^还款次数))/((1+利率/12)^还款次数-1) ,2)
            repaymentAmount =
                    (
                            summaryBO.getPrincipal().multiply(summaryBO.getRate()).divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)
                    ).multiply(
                            (
                                    new BigDecimal(1).add(
                                            summaryBO.getRate().divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)
                                    )
                            ).pow(summaryBO.getRepaymentTimes())
                    ).divide(
                            (
                                    (
                                            new BigDecimal(1).add(
                                                    summaryBO.getRate().divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)
                                            )
                                    ).pow(summaryBO.getRepaymentTimes())
                            ).subtract(new BigDecimal(1)),2,BigDecimal.ROUND_HALF_UP
                    );
            summaryBO.setRepaymentAmount(repaymentAmount);

            /**
             * 第4步:等额本息
             * 计算实际本金余额、实际现金流、实际利息流、余额累计
             */
            calculateInterestActualAmountInfo(summaryBO,boList);
            /**
             * 第5步:等额本息
             * 计算本金余额、现金流、利息流
             */
            calculateInterestAmountInfo(summaryBO,boList);

        }
        //等额本金
        else if(loanRepaymentModeType == FtpLoanRepaymentModeTypeEnum.LOAN_REPAYMENT_MODE3.getValue()){

            //等额本金无利率
            customerRate = new BigDecimal("0");
            summaryBO.setRate(customerRate);
            //等额本金信息汇总:还款额=ROUND(本金/还款次数,2)
            repaymentAmount = summaryBO.getPrincipal().divide(new BigDecimal(summaryBO.getRepaymentTimes()),2,BigDecimal.ROUND_HALF_UP);
            summaryBO.setRepaymentAmount(repaymentAmount);

            /**
             * 第4步:等额本金
             * 计算实际本金余额、余额累计
             */
            calculatePrincipalActualAmountInfo(summaryBO,boList);

            /**
             * 第5步:等额本金
             * 计算本金余额、现金流
             */
            calculatePrincipalAmountInfo(summaryBO,boList);
        }

        System.out.println("==============================================");

        /**
         * 第6步
         * 计算下限期限、上线期限、下限利率、上线利率、现金流、期限、利率
         */
        calculateConfigUnderUpperDays(summaryBO,boList,ftpDepositLoanRateDetailBOMap);
        //int listSize = boList.size();
        //for (int i = 0; i < listSize; i++) {
        //    System.out.println(
        //            "业务日期businessDate:" + boList.get(i).getBusinessDate() +
        //                    ",定价日期pricingDate:" + boList.get(i).getPricingDate() +
        //                    ",实际本金余额ActualPrincipalBalance:" + boList.get(i).getActualPrincipalBalance() +
        //                    ",实际现金流ActualCashFlow:" + boList.get(i).getActualCashFlow() +
        //                    ",实际利息流ActualInterestFlow:" + boList.get(i).getActualInterestFlow() +
        //                    ",本金余额PrincipalBalance:" + boList.get(i).getPrincipalBalance() +
        //                    ",现金流CashFlow:" + boList.get(i).getCashFlow() +
        //                    ",期限Term:" + boList.get(i).getTerm() +
        //                    ",(实际)次数Times:" + boList.get(i).getActualTimes() +
        //                    ",利息流InterestFlow:" + boList.get(i).getInterestFlow() +
        //                    ",余额累计ActualBalanceAccumulation:" + boList.get(i).getActualBalanceAccumulation() +
        //                    ",对应利率interestRate=" + boList.get(i).getInterestRate() +
        //                    ",现金流*期限calculateVal01=" + boList.get(i).getCalculateVal01() +
        //                    ",现金流*期限*利率calculateVal02=" + boList.get(i).getCalculateVal02() +
        //                    ",下限期限configUnderDay=" + boList.get(i).getConfigUnderDay() +
        //                    ",上限期限configUpperDay=" + boList.get(i).getConfigUpperDay() +
        //                    ",下限利率configUnderRate=" + boList.get(i).getConfigUnderRate() +
        //                    ",上限利率configUpperRate=" + boList.get(i).getConfigUpperRate());
        //}

        /**
         * 第7步
         * 计算基础价格
         */
        calculateActualBasicPriceInfo(summaryBO);

        /**
         * 第N步
         * 输出最终结果
         */
        //System.out.println(
        //        ", repaymentFrequency还款频率=" + summaryBO.getRepaymentFrequency() +
        //        ", cashFlowMaturityDate现金流/业务到期日='" + summaryBO.getCashFlowMaturityDate() + '\'' +
        //        ", repricingDueDate重定价到期日='" + summaryBO.getRepricingDueDate() + '\'' +
        //                ", repaymentTimes还款次数=" + summaryBO.getRepaymentTimes() +
        //                ", principal本金=" + summaryBO.getPrincipal() +
        //                ", rate利率=" + summaryBO.getRate() +
        //                ", repaymentAmount每期还款额=" + summaryBO.getRepaymentAmount() +
        //                ", calculateVal02现金流*期限*利率=" + summaryBO.getCalculateVal02() +
        //                ", calculateVal01现金流*期限(求和)=" + summaryBO.getCalculateVal01() +
        //                ", basicPrice基础价格=" + summaryBO.getBasicPrice() +
        //                ", balanceAccumulation余额累计=" + summaryBO.getBalanceAccumulation());

        return summaryBO;

    }

    /**
     * 第7步
     * 计算基础价格
     */
    private void calculateActualBasicPriceInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO){
        //等额本息汇总:基础价格(calculateVal02/calculateVal01,4)
        summaryBO.setBasicPrice(summaryBO.getCalculateVal02().divide(summaryBO.getCalculateVal01(),4,BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 初始化收益率曲线转置数据
     */
    private Map<String,FtpDepositLoanRateDetailBO> dateInitFtpDepositLoanRateData(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO){

        //dateStrInit = "2024-02-29";

        /**
         * 这里要查ftp_deposit_loan_rate_config所有数据,都要改
         */
        Map<String,FtpDepositLoanRateDetailBO> ftpDepositLoanRateDetailBOMap = new HashMap<>();
        //起始日
        String dateStrInit = summaryBO.getBusinessBeginDate();

        //重定价频率(月)(3,6,12)(方法中默认12)(当利率类型为固定时:不使用重定价频率)
        Integer repricingFrequencyType = summaryBO.getRepricingFrequencyType();
        //等额本息汇总:还款频率(1,3,6,12)(只选1和3)
        Integer repaymentFrequency = summaryBO.getRepaymentFrequency();
        //等额本息汇总:利率类型(固定:1,浮动:2)(方法中默认2)
        Integer interestRateType = summaryBO.getInterestRateType();

        try {

            Map<String,FtpDepositLoanRateConfig> configKeyMap = ftpDepositLoanRateConfigMapper.selectBaseListByConfigTypeOfConfigKeyMap(FtpPricingParamTypeEnum.DEPOSIT_LOAD_YIELD_CURVE.getValue());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_N = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.N_0.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_1W = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.W_1.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_2W = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.W_2.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_1M = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.M_1.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_3M = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.M_3.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_6M = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.M_6.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_9M = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.M_9.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_1Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_1.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_2Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_2.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_3Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_3.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_5Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_5.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_10Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_10.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_15Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_15.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_20Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_20.getConfigKey());
            FtpDepositLoanRateConfig ftpDepositLoanRateConfig_30Y = configKeyMap.get(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigKey());

            LocalDate localDateInit = LocalDate.parse(dateStrInit, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            //还款频率1
            if(repaymentFrequency == FtpRepaymentFrequencyTypeEnum.REPAYMENT_FREQUENCY1.getValue()) {

                LocalDate localDateInit_N = localDateInit.plusDays(1);
                localDateInit_N = DateUtils.dateInitCheckFtpDataProcess(localDateInit, localDateInit_N);

                LocalDate localDateInit_1W = localDateInit.plusWeeks(1);
                localDateInit_1W = DateUtils.dateInitCheckFtpDataProcess(localDateInit, localDateInit_1W);

                FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_N = new FtpDepositLoanRateDetailBO();
                ftpDepositLoanRateDetailBO_N.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.N_0.getConfigKey());
                ftpDepositLoanRateDetailBO_N.setConfigName(FtpDepositLoanRateConfigKeyEnum.N_0.getConfigName());
                ftpDepositLoanRateDetailBO_N.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.W_1.getConfigKey());
                //TODO 这里需要查MYSQL
                ftpDepositLoanRateDetailBO_N.setConfigUnderRate(ftpDepositLoanRateConfig_N.getConfigRate());
                ftpDepositLoanRateDetailBO_N.setConfigUpperRate(ftpDepositLoanRateConfig_1W.getConfigRate());
                ftpDepositLoanRateDetailBO_N.setConfigUnderDay((int) localDateInit.until(localDateInit_N, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_N.setConfigUpperDay((int) localDateInit.until(localDateInit_1W, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_N.setConfigUnderDate(dateStrInit);
                ftpDepositLoanRateDetailBO_N.setConfigUpperDate(localDateInit_1W.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.N_0.getConfigKey(), ftpDepositLoanRateDetailBO_N);

                LocalDate localDateInit_2W = localDateInit.plusWeeks(2);
                localDateInit_2W = DateUtils.dateInitCheckFtpDataProcess(localDateInit, localDateInit_2W);

                FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_1W = new FtpDepositLoanRateDetailBO();
                ftpDepositLoanRateDetailBO_1W.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.W_1.getConfigKey());
                ftpDepositLoanRateDetailBO_1W.setConfigName(FtpDepositLoanRateConfigKeyEnum.W_1.getConfigName());
                ftpDepositLoanRateDetailBO_1W.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.W_2.getConfigKey());
                //TODO 这里需要查MYSQL
                ftpDepositLoanRateDetailBO_1W.setConfigUnderRate(ftpDepositLoanRateConfig_1W.getConfigRate());
                ftpDepositLoanRateDetailBO_1W.setConfigUpperRate(ftpDepositLoanRateConfig_2W.getConfigRate());
                ftpDepositLoanRateDetailBO_1W.setConfigUnderDay((int) localDateInit.until(localDateInit_1W, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_1W.setConfigUpperDay((int) localDateInit.until(localDateInit_2W, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_1W.setConfigUnderDate(localDateInit_1W.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBO_1W.setConfigUpperDate(localDateInit_2W.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.W_1.getConfigKey(), ftpDepositLoanRateDetailBO_1W);

                LocalDate localDateInit_1M = localDateInit.plusMonths(1);
                localDateInit_1M = DateUtils.dateInitCheckFtpDataProcess(localDateInit, localDateInit_1M);

                FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_2W = new FtpDepositLoanRateDetailBO();
                ftpDepositLoanRateDetailBO_2W.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.W_2.getConfigKey());
                ftpDepositLoanRateDetailBO_2W.setConfigName(FtpDepositLoanRateConfigKeyEnum.W_2.getConfigName());
                ftpDepositLoanRateDetailBO_2W.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.M_1.getConfigKey());
                //TODO 这里需要查MYSQL
                ftpDepositLoanRateDetailBO_2W.setConfigUnderRate(ftpDepositLoanRateConfig_2W.getConfigRate());
                ftpDepositLoanRateDetailBO_2W.setConfigUpperRate(ftpDepositLoanRateConfig_1M.getConfigRate());
                ftpDepositLoanRateDetailBO_2W.setConfigUnderDay((int) localDateInit.until(localDateInit_2W, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_2W.setConfigUpperDay((int) localDateInit.until(localDateInit_1M, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_2W.setConfigUnderDate(localDateInit_2W.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBO_2W.setConfigUpperDate(localDateInit_1M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.W_2.getConfigKey(), ftpDepositLoanRateDetailBO_2W);

                LocalDate localDateInit_3M = localDateInit.plusMonths(3);
                localDateInit_3M = DateUtils.dateInitCheckFtpDataProcess(localDateInit, localDateInit_3M);

                FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_1M = new FtpDepositLoanRateDetailBO();
                ftpDepositLoanRateDetailBO_1M.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.M_1.getConfigKey());
                ftpDepositLoanRateDetailBO_1M.setConfigName(FtpDepositLoanRateConfigKeyEnum.M_1.getConfigName());
                ftpDepositLoanRateDetailBO_1M.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.M_3.getConfigKey());
                //TODO 这里需要查MYSQL
                ftpDepositLoanRateDetailBO_1M.setConfigUnderRate(ftpDepositLoanRateConfig_1M.getConfigRate());
                ftpDepositLoanRateDetailBO_1M.setConfigUpperRate(ftpDepositLoanRateConfig_3M.getConfigRate());
                ftpDepositLoanRateDetailBO_1M.setConfigUnderDay((int) localDateInit.until(localDateInit_1M, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_1M.setConfigUpperDay((int) localDateInit.until(localDateInit_3M, ChronoUnit.DAYS));
                ftpDepositLoanRateDetailBO_1M.setConfigUnderDate(localDateInit_1M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBO_1M.setConfigUpperDate(localDateInit_3M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.M_1.getConfigKey(), ftpDepositLoanRateDetailBO_1M);

            }

            //其余还款频率1和3共用
            LocalDate localDateInit_3M = localDateInit.plusMonths(3);
            localDateInit_3M = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_3M);

            LocalDate localDateInit_6M = localDateInit.plusMonths(6);
            localDateInit_6M = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_6M);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_3M = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_3M.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.M_3.getConfigKey());
            ftpDepositLoanRateDetailBO_3M.setConfigName(FtpDepositLoanRateConfigKeyEnum.M_3.getConfigName());
            ftpDepositLoanRateDetailBO_3M.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.M_6.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_3M.setConfigUnderRate(ftpDepositLoanRateConfig_3M.getConfigRate());
            ftpDepositLoanRateDetailBO_3M.setConfigUpperRate(ftpDepositLoanRateConfig_6M.getConfigRate());
            ftpDepositLoanRateDetailBO_3M.setConfigUnderDay((int)localDateInit.until(localDateInit_3M, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_3M.setConfigUpperDay((int)localDateInit.until(localDateInit_6M, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_3M.setConfigUnderDate(localDateInit_3M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_3M.setConfigUpperDate(localDateInit_6M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.M_3.getConfigKey(),ftpDepositLoanRateDetailBO_3M);

            LocalDate localDateInit_9M = localDateInit.plusMonths(9);
            localDateInit_9M = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_9M);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_6M = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_6M.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.M_6.getConfigKey());
            ftpDepositLoanRateDetailBO_6M.setConfigName(FtpDepositLoanRateConfigKeyEnum.M_6.getConfigName());
            ftpDepositLoanRateDetailBO_6M.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.M_9.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_6M.setConfigUnderRate(ftpDepositLoanRateConfig_6M.getConfigRate());
            ftpDepositLoanRateDetailBO_6M.setConfigUpperRate(ftpDepositLoanRateConfig_9M.getConfigRate());
            ftpDepositLoanRateDetailBO_6M.setConfigUnderDay((int)localDateInit.until(localDateInit_6M, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_6M.setConfigUpperDay((int)localDateInit.until(localDateInit_9M, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_6M.setConfigUnderDate(localDateInit_6M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_6M.setConfigUpperDate(localDateInit_9M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.M_6.getConfigKey(),ftpDepositLoanRateDetailBO_6M);

            LocalDate localDateInit_12M_1Y = localDateInit.plusYears(1);
            localDateInit_12M_1Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_12M_1Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_9M = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_9M.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.M_9.getConfigKey());
            ftpDepositLoanRateDetailBO_9M.setConfigName(FtpDepositLoanRateConfigKeyEnum.M_9.getConfigName());
            ftpDepositLoanRateDetailBO_9M.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_1.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_9M.setConfigUnderRate(ftpDepositLoanRateConfig_9M.getConfigRate());
            ftpDepositLoanRateDetailBO_9M.setConfigUpperRate(ftpDepositLoanRateConfig_1Y.getConfigRate());
            ftpDepositLoanRateDetailBO_9M.setConfigUnderDay((int)localDateInit.until(localDateInit_9M, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_9M.setConfigUpperDay((int)localDateInit.until(localDateInit_12M_1Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_9M.setConfigUnderDate(localDateInit_9M.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_9M.setConfigUpperDate(localDateInit_12M_1Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.M_9.getConfigKey(),ftpDepositLoanRateDetailBO_9M);

            LocalDate localDateInit_2Y = localDateInit.plusYears(2);
            localDateInit_2Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_2Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_12M_1Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_1.getConfigKey());
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_1.getConfigName());
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_2.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUnderRate(ftpDepositLoanRateConfig_1Y.getConfigRate());
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUpperRate(ftpDepositLoanRateConfig_2Y.getConfigRate());
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUnderDay((int)localDateInit.until(localDateInit_12M_1Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUpperDay((int)localDateInit.until(localDateInit_2Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUnderDate(localDateInit_12M_1Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_12M_1Y.setConfigUpperDate(localDateInit_2Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_1.getConfigKey(),ftpDepositLoanRateDetailBO_12M_1Y);

            LocalDate localDateInit_3Y = localDateInit.plusYears(3);
            localDateInit_3Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_3Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_2Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_2Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_2.getConfigKey());
            ftpDepositLoanRateDetailBO_2Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_2.getConfigName());
            ftpDepositLoanRateDetailBO_2Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_3.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_2Y.setConfigUnderRate(ftpDepositLoanRateConfig_2Y.getConfigRate());
            ftpDepositLoanRateDetailBO_2Y.setConfigUpperRate(ftpDepositLoanRateConfig_3Y.getConfigRate());
            ftpDepositLoanRateDetailBO_2Y.setConfigUnderDay((int)localDateInit.until(localDateInit_2Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_2Y.setConfigUpperDay((int)localDateInit.until(localDateInit_3Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_2Y.setConfigUnderDate(localDateInit_2Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_2Y.setConfigUpperDate(localDateInit_3Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_2.getConfigKey(),ftpDepositLoanRateDetailBO_2Y);

            LocalDate localDateInit_5Y = localDateInit.plusYears(5);
            localDateInit_5Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_5Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_3Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_3Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_3.getConfigKey());
            ftpDepositLoanRateDetailBO_3Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_3.getConfigName());
            ftpDepositLoanRateDetailBO_3Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_5.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_3Y.setConfigUnderRate(ftpDepositLoanRateConfig_3Y.getConfigRate());
            ftpDepositLoanRateDetailBO_3Y.setConfigUpperRate(ftpDepositLoanRateConfig_5Y.getConfigRate());
            ftpDepositLoanRateDetailBO_3Y.setConfigUnderDay((int)localDateInit.until(localDateInit_3Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_3Y.setConfigUpperDay((int)localDateInit.until(localDateInit_5Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_3Y.setConfigUnderDate(localDateInit_3Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_3Y.setConfigUpperDate(localDateInit_5Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_3.getConfigKey(),ftpDepositLoanRateDetailBO_3Y);

            LocalDate localDateInit_10Y = localDateInit.plusYears(10);
            localDateInit_10Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_10Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_5Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_5Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_5.getConfigKey());
            ftpDepositLoanRateDetailBO_5Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_5.getConfigName());
            ftpDepositLoanRateDetailBO_5Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_10.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_5Y.setConfigUnderRate(ftpDepositLoanRateConfig_5Y.getConfigRate());
            ftpDepositLoanRateDetailBO_5Y.setConfigUpperRate(ftpDepositLoanRateConfig_10Y.getConfigRate());
            ftpDepositLoanRateDetailBO_5Y.setConfigUnderDay((int)localDateInit.until(localDateInit_5Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_5Y.setConfigUpperDay((int)localDateInit.until(localDateInit_10Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_5Y.setConfigUnderDate(localDateInit_5Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_5Y.setConfigUpperDate(localDateInit_10Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_5.getConfigKey(),ftpDepositLoanRateDetailBO_5Y);

            LocalDate localDateInit_15Y = localDateInit.plusYears(15);
            localDateInit_15Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_15Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_10Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_10Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_10.getConfigKey());
            ftpDepositLoanRateDetailBO_10Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_10.getConfigName());
            ftpDepositLoanRateDetailBO_10Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_15.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_10Y.setConfigUnderRate(ftpDepositLoanRateConfig_10Y.getConfigRate());
            ftpDepositLoanRateDetailBO_10Y.setConfigUpperRate(ftpDepositLoanRateConfig_15Y.getConfigRate());
            ftpDepositLoanRateDetailBO_10Y.setConfigUnderDay((int)localDateInit.until(localDateInit_10Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_10Y.setConfigUpperDay((int)localDateInit.until(localDateInit_15Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_10Y.setConfigUnderDate(localDateInit_10Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_10Y.setConfigUpperDate(localDateInit_15Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_10.getConfigKey(),ftpDepositLoanRateDetailBO_10Y);

            LocalDate localDateInit_20Y = localDateInit.plusYears(20);
            localDateInit_20Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_20Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_15Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_15Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_15.getConfigKey());
            ftpDepositLoanRateDetailBO_15Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_15.getConfigName());
            ftpDepositLoanRateDetailBO_15Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_20.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_15Y.setConfigUnderRate(ftpDepositLoanRateConfig_15Y.getConfigRate());
            ftpDepositLoanRateDetailBO_15Y.setConfigUpperRate(ftpDepositLoanRateConfig_20Y.getConfigRate());
            ftpDepositLoanRateDetailBO_15Y.setConfigUnderDay((int)localDateInit.until(localDateInit_15Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_15Y.setConfigUpperDay((int)localDateInit.until(localDateInit_20Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_15Y.setConfigUnderDate(localDateInit_15Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_15Y.setConfigUpperDate(localDateInit_20Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_15.getConfigKey(),ftpDepositLoanRateDetailBO_15Y);

            LocalDate localDateInit_30Y = localDateInit.plusYears(30);
            localDateInit_30Y = DateUtils.dateInitCheckFtpDataProcess(localDateInit,localDateInit_30Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_20Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_20Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_20.getConfigKey());
            ftpDepositLoanRateDetailBO_20Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_20.getConfigName());
            ftpDepositLoanRateDetailBO_20Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_20Y.setConfigUnderRate(ftpDepositLoanRateConfig_20Y.getConfigRate());
            ftpDepositLoanRateDetailBO_20Y.setConfigUpperRate(ftpDepositLoanRateConfig_30Y.getConfigRate());
            ftpDepositLoanRateDetailBO_20Y.setConfigUnderDay((int)localDateInit.until(localDateInit_20Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_20Y.setConfigUpperDay((int)localDateInit.until(localDateInit_30Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_20Y.setConfigUnderDate(localDateInit_20Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_20Y.setConfigUpperDate(localDateInit_30Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_20.getConfigKey(),ftpDepositLoanRateDetailBO_20Y);

            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO_30Y = new FtpDepositLoanRateDetailBO();
            ftpDepositLoanRateDetailBO_30Y.setConfigUnderKey(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigKey());
            ftpDepositLoanRateDetailBO_30Y.setConfigName(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigName());
            ftpDepositLoanRateDetailBO_30Y.setConfigUpperKey(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigKey());
            //TODO 这里需要查MYSQL
            ftpDepositLoanRateDetailBO_30Y.setConfigUnderRate(ftpDepositLoanRateConfig_30Y.getConfigRate());
            ftpDepositLoanRateDetailBO_30Y.setConfigUpperRate(ftpDepositLoanRateConfig_30Y.getConfigRate());
            ftpDepositLoanRateDetailBO_30Y.setConfigUnderDay((int)localDateInit.until(localDateInit_30Y, ChronoUnit.DAYS));
            ftpDepositLoanRateDetailBO_30Y.setConfigUpperDay(99999);
            ftpDepositLoanRateDetailBO_30Y.setConfigUnderDate(localDateInit_30Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBO_30Y.setConfigUpperDate(localDateInit_30Y.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            ftpDepositLoanRateDetailBOMap.put(FtpDepositLoanRateConfigKeyEnum.Y_30.getConfigKey(),ftpDepositLoanRateDetailBO_30Y);

            //ftpDepositLoanRateDetailBOMap.entrySet().forEach(map -> {
            //
            //    System.out.println(map.getKey() + "~~~~~~~~~~~~~" + map.getValue());
            //
            //});

        }catch (Exception e){
            e.printStackTrace();
        }

        return ftpDepositLoanRateDetailBOMap;

    }
    //
    ///**
    // * 公共方法:处理日期,补日期数据
    // * TODO:二月/闰年/29号/30号/31号
    // */
    //private LocalDate dateInitCheckFtpDataProcess(LocalDate localDateInit,LocalDate localDateNext){
    //
    //    int localDateMonthNext = localDateNext.getMonth().getValue();
    //    if (localDateMonthNext != 2) {
    //        int localDateDayCurrent = localDateInit.getDayOfMonth();
    //        int localDateDayNext = localDateNext.getDayOfMonth();
    //        if(localDateDayCurrent > 30 && localDateDayNext == 30){
    //            localDateNext = LocalDate.of(localDateNext.getYear(),localDateMonthNext + 1,localDateDayCurrent - localDateDayNext);
    //        }
    //    } else {
    //        int localDateDayCurrent = localDateInit.getDayOfMonth();
    //        if (localDateDayCurrent > 28) {
    //            int localDateDayNext = localDateNext.getDayOfMonth();
    //            int difference = localDateDayCurrent - localDateDayNext;
    //            int localDateYearNext = localDateNext.getYear();
    //            if ((localDateYearNext % 4 == 0 && localDateYearNext % 100 != 0) || localDateYearNext % 400 == 0) {
    //                if(difference > 0){
    //                    localDateNext = LocalDate.of(localDateYearNext,3,difference);
    //                }
    //            }else{
    //                localDateNext = LocalDate.of(localDateYearNext,3,difference);
    //            }
    //        }
    //    }
    //    return localDateNext;
    //}

    /**
     * 第6步
     * 计算下限期限、上线期限、下限利率、上线利率、现金流、期限、利率
     */
    private void calculateConfigUnderUpperDays(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                      List<EcardFtpAverageCapitalPlusInterestBO> underUpperDaysInfoList,
                                                      Map<String,FtpDepositLoanRateDetailBO> ftpDepositLoanRateDetailBOMap){

        //等额本息汇总:现金流*期限(求和)
        BigDecimal calculateVal01Sum = summaryBO.getCalculateVal01();
        //等额本息汇总:现金流*期限*利率(求和)
        BigDecimal calculateVal02Sum = summaryBO.getCalculateVal02();

        //等额本息汇总:还款频率(1,3,6,12)(只选1和3)
        Integer repaymentFrequency = summaryBO.getRepaymentFrequency();

        //计算非实际相关字段的总条数
        int limitTime = summaryBO.getTotalNum();

        //注意这里是集合的总条数
        for (int i = 1; i <= limitTime; i++) {

            int ftpUnderUpperDateRelationNum = i;
            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = underUpperDaysInfoList.get(ftpUnderUpperDateRelationNum);
            if(i == limitTime){
                //等额本息汇总:利率类型(固定:1,浮动:2)
                Integer interestRateType = summaryBO.getInterestRateType();
                if(interestRateType == 1 && limitTime > 1){
                    //最后一行,浮动会变动,而固定直接和上一种的上下限内容相同
                    ftpUnderUpperDateRelationNum = i - 1;
                }
            }
            //通过还款频率类型与条数获取期限标识
            FtpUnderUpperDateRelationEnum ftpUnderUpperDateRelationEnum = FtpUnderUpperDateRelationEnum.values(repaymentFrequency,ftpUnderUpperDateRelationNum);
            //下限标识
            String configUnderKey = ftpUnderUpperDateRelationEnum.getConfigUnderKey();
            averageCapitalPlusInterestBOInside.setConfigUnderKey(configUnderKey);
            FtpDepositLoanRateDetailBO ftpDepositLoanRateDetailBO = ftpDepositLoanRateDetailBOMap.get(configUnderKey);
            //下限日期
            averageCapitalPlusInterestBOInside.setConfigUnderDate(ftpDepositLoanRateDetailBO.getConfigUnderDate());
            //下限期限
            int configUnderDay = ftpDepositLoanRateDetailBO.getConfigUnderDay();
            averageCapitalPlusInterestBOInside.setConfigUnderDay(configUnderDay);
            //下限利率
            averageCapitalPlusInterestBOInside.setConfigUnderRate(new BigDecimal(ftpDepositLoanRateDetailBO.getConfigUnderRate()));
            //上限标识
            averageCapitalPlusInterestBOInside.setConfigUpperKey(ftpDepositLoanRateDetailBO.getConfigUpperKey());
            //上限日期
            averageCapitalPlusInterestBOInside.setConfigUpperDate(ftpDepositLoanRateDetailBO.getConfigUpperDate());
            //上限期限
            int configUpperDay = ftpDepositLoanRateDetailBO.getConfigUpperDay();
            averageCapitalPlusInterestBOInside.setConfigUpperDay(configUpperDay);
            //上限利率
            averageCapitalPlusInterestBOInside.setConfigUpperRate(new BigDecimal(ftpDepositLoanRateDetailBO.getConfigUpperRate()));

            /**
             * 对应利率
             * if(上线期限==下限期限){
             *      对应利率=下限利率;
             * }else{
             *      对应利率=((期限-下限期限)*(上限利率-下线利率)/(上限期限-下限期限)) + 下线利率
             * }
             */
            BigDecimal interestRate;
            if(configUpperDay == configUnderDay){
                interestRate = averageCapitalPlusInterestBOInside.getConfigUpperRate();
            }else{
                interestRate = (
                        (
                                new BigDecimal(averageCapitalPlusInterestBOInside.getTerm()).subtract(new BigDecimal(configUnderDay))
                        ).multiply(
                                averageCapitalPlusInterestBOInside.getConfigUpperRate().subtract(averageCapitalPlusInterestBOInside.getConfigUnderRate())
                        ).divide(
                                new BigDecimal(configUpperDay).subtract(new BigDecimal(configUnderDay)),16,BigDecimal.ROUND_HALF_UP
                        )
                ).add(averageCapitalPlusInterestBOInside.getConfigUnderRate()).setScale(9,BigDecimal.ROUND_HALF_UP);
            }
            averageCapitalPlusInterestBOInside.setInterestRate(interestRate);

            /**
             * 现金流cashFlow * 期限term
             */
            BigDecimal calculateVal01 = averageCapitalPlusInterestBOInside.getCashFlow().multiply
                    (new BigDecimal(averageCapitalPlusInterestBOInside.getTerm()).setScale(2,BigDecimal.ROUND_HALF_UP));
            averageCapitalPlusInterestBOInside.setCalculateVal01(calculateVal01);
            //等额本息汇总:现金流*期限(求和)
            calculateVal01Sum = calculateVal01Sum.add(calculateVal01);

            /**
             * 现金流cashFlow * 期限term *利率interestRate
             */
            BigDecimal calculateVal02 = averageCapitalPlusInterestBOInside.getCashFlow().multiply
                    (new BigDecimal(averageCapitalPlusInterestBOInside.getTerm())).multiply
                    (averageCapitalPlusInterestBOInside.getInterestRate()).setScale(4,BigDecimal.ROUND_HALF_UP);
            averageCapitalPlusInterestBOInside.setCalculateVal02(calculateVal02);
            //等额本息汇总:现金流*期限*利率(求和)
            calculateVal02Sum = calculateVal02Sum.add(calculateVal02);

        }
        //等额本息汇总:现金流*期限(求和)
        summaryBO.setCalculateVal01(calculateVal01Sum);
        //等额本息汇总:现金流*期限*利率(求和)
        summaryBO.setCalculateVal02(calculateVal02Sum);
    }



    /**
     * 第5步:等额本息
     * 计算本金余额、现金流、利息流
     */
    private void calculateInterestAmountInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                    List<EcardFtpAverageCapitalPlusInterestBO> amountInfoList){



        //重定价到期日
        String repricingDueDate = summaryBO.getRepricingDueDate();
        LocalDate localRepricingDueDate = LocalDate.parse(repricingDueDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //每期还款额
        BigDecimal repaymentAmount = summaryBO.getRepaymentAmount();

        //计算利率的次方值
        int actualPowNum = summaryBO.getActualPowNum();
        //期数:计算非实际相关字段的总条数
        int limitTime = summaryBO.getTotalNum();

        //本金余额
        BigDecimal corpusLeft = summaryBO.getPrincipal();
        //利率
        BigDecimal rate = summaryBO.getRate();

        //本金余额
        BigDecimal corpusLeftMon = corpusLeft;
        //每期贷款利率
        BigDecimal ratePow = ((rate.divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)).add(new BigDecimal(1))).pow(actualPowNum).setScale(16,BigDecimal.ROUND_HALF_UP);
        //每月还本付息金额
        BigDecimal capMon = corpusLeft.multiply(rate.divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)).multiply(ratePow).divide(ratePow.subtract(new BigDecimal(1)),2,BigDecimal.ROUND_HALF_UP);
        //现金流
        BigDecimal corpusMon;
        //利息流
        BigDecimal restMon;
        //注意这里是集合的总条数
        for (int i = 1; i <= limitTime; i++) {

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOLast = amountInfoList.get(i - 1);
            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = amountInfoList.get(i);

            //上一次的本金余额
            corpusLeftMon = averageCapitalPlusInterestBOLast.getPrincipalBalance();
            //利息流
            restMon = corpusLeftMon.multiply
                    (
                            rate
                                    //日期差值动态值
                                    .multiply(new BigDecimal(averageCapitalPlusInterestBOInside.getTermInterval()))
                    ).divide(new BigDecimal(360),16,BigDecimal.ROUND_HALF_UP)
                    .setScale(2,BigDecimal.ROUND_HALF_UP);
            //定价日期
            String pricingDate = averageCapitalPlusInterestBOInside.getPricingDate();
            LocalDate localPricingDate = LocalDate.parse(pricingDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            if(localPricingDate.isEqual(localRepricingDueDate)){
                corpusMon = corpusLeftMon;
            }else{
                corpusMon = repaymentAmount.subtract(restMon);
            }

            //本金余额
            corpusLeftMon = corpusLeftMon.subtract(corpusMon).setScale(2,BigDecimal.ROUND_HALF_UP);
            //本金余额
            averageCapitalPlusInterestBOInside.setPrincipalBalance(corpusLeftMon);
            //每期贷款利率
            averageCapitalPlusInterestBOInside.setRateFlow(ratePow);
            //每月还本付息金额
            averageCapitalPlusInterestBOInside.setRepayCapitalInterest(capMon);
            //现金流
            averageCapitalPlusInterestBOInside.setCashFlow(corpusMon);
            //利息流
            averageCapitalPlusInterestBOInside.setInterestFlow(restMon);

        }

    }


    /**
     * 第5步:等额本金
     * 计算本金余额、利息流
     */
    private void calculatePrincipalAmountInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                     List<EcardFtpAverageCapitalPlusInterestBO> amountInfoList){

        //还款额
        BigDecimal repaymentAmount = summaryBO.getRepaymentAmount();
        //重定价到期日
        String repricingDueDate = summaryBO.getRepricingDueDate();
        LocalDate localRepricingDueDate = LocalDate.parse(repricingDueDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        //期数:计算非实际相关字段的总条数
        int limitTime = summaryBO.getTotalNum();

        //注意这里是集合的总条数
        for (int i = 1; i <= limitTime; i++) {

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = amountInfoList.get(i);
            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOLast = amountInfoList.get(i-1);

            //定价日期
            String pricingDate = averageCapitalPlusInterestBOInside.getPricingDate();
            LocalDate localPricingDate = LocalDate.parse(pricingDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            if(!localPricingDate.isEqual(localRepricingDueDate)){
                //现金流
                BigDecimal cashFlow = repaymentAmount;
                averageCapitalPlusInterestBOInside.setCashFlow(cashFlow);
                //本金余额
                BigDecimal principalBalance = averageCapitalPlusInterestBOLast.getPrincipalBalance()
                        .subtract(averageCapitalPlusInterestBOInside.getCashFlow());
                averageCapitalPlusInterestBOInside.setPrincipalBalance(principalBalance);
            }else{
                //现金流
                BigDecimal cashFlow = averageCapitalPlusInterestBOLast.getPrincipalBalance();
                averageCapitalPlusInterestBOInside.setCashFlow(cashFlow);
                //本金余额
                averageCapitalPlusInterestBOInside.setPrincipalBalance(new BigDecimal("0"));
            }

        }

    }



    /**
     * 第3步
     * 计算定价日期及其日期间隔等
     */
    private void calculateRepricingDateInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                   List<EcardFtpAverageCapitalPlusInterestBO> repricingDateList){


        //起始日
        LocalDate localDateInit = LocalDate.parse(summaryBO.getBusinessBeginDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //到期日
        LocalDate localDateFinally = LocalDate.parse(summaryBO.getBusinessEndDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //重定价到期日
        //String dateStrRepricing = "2025-12-31";
        LocalDate localDateRepricing = LocalDate.parse(summaryBO.getRepricingDueDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        //还款频率
        int repaymentFrequency = summaryBO.getRepaymentFrequency();
        //期数:计算非实际相关字段的总条数
        int limitTime = summaryBO.getTotalNum();

        LocalDate localDateNext = null;
        //"sheet-等额本息"次数
        int actualLimitNum = 1;
        boolean flag = true;
        //limitTime = summaryBO.getTotalNum();
        for (int i = 1; i <= limitTime; i++) {
            if(flag){
                localDateNext = localDateInit.plusMonths(repaymentFrequency);
            }else{
                localDateNext = localDateNext.plusMonths(repaymentFrequency);
            }
            int localDateMonthNext = localDateNext.getMonth().getValue();
            if (localDateMonthNext != 2) {
                int localDateDayCurrent = localDateInit.getDayOfMonth();
                int localDateDayNext = localDateNext.getDayOfMonth();
                if(localDateDayCurrent > 30 && localDateDayNext == 30){
                    localDateNext = LocalDate.of(localDateNext.getYear(),localDateMonthNext + 1,localDateDayCurrent - localDateDayNext);
                }
                flag = true;
            } else {
                int localDateDayCurrent = localDateInit.getDayOfMonth();
                if (localDateDayCurrent > 28) {
                    int localDateDayNext = localDateNext.getDayOfMonth();
                    int difference = localDateDayCurrent - localDateDayNext;
                    int localDateYearNext = localDateNext.getYear();
                    if ((localDateYearNext % 4 == 0 && localDateYearNext % 100 != 0) || localDateYearNext % 400 == 0) {
                        if(difference > 0){
                            localDateNext = LocalDate.of(localDateYearNext,3,difference);
                        }
                    }else{
                        localDateNext = LocalDate.of(localDateYearNext,3,difference);
                    }
                    flag = false;
                }
            }

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = repricingDateList.get(i);
            //次数
            averageCapitalPlusInterestBOInside.setTimes(actualLimitNum);

            //"sheet-等额本息"业务日期
            String pricingDate;
            //最后一个日期值的处理
            if(i != limitTime){
                if(localDateNext.isBefore(localDateRepricing)){
                    pricingDate = localDateNext.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    averageCapitalPlusInterestBOInside.setPricingDate(pricingDate);
                    //期限间隔
                    averageCapitalPlusInterestBOInside.setTermInterval((int)localDateInit.until(localDateNext, ChronoUnit.DAYS));
                    //期限
                    Integer term = repricingDateList.get(actualLimitNum - 1).getTerm() + averageCapitalPlusInterestBOInside.getTermInterval();
                    averageCapitalPlusInterestBOInside.setTerm(term);
                    //设置当前日期对象(用于下次日期的处理)
                    localDateInit = localDateNext;
                    //"sheet-等额本息"次数
                    actualLimitNum++;
                }else{
                    //如果计算得到的下一个日期localDateNext大于现金流到期日/业务到期日localDateFinally,那么取localDateFinally.
                    pricingDate = localDateRepricing.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    averageCapitalPlusInterestBOInside.setPricingDate(pricingDate);
                    //等额本息汇总:定价日期最后一个
                    summaryBO.setPricingEndDate(pricingDate);
                    //期限间隔
                    averageCapitalPlusInterestBOInside.setTermInterval((int)localDateInit.until(localDateRepricing, ChronoUnit.DAYS));
                    //期限
                    Integer term = repricingDateList.get(actualLimitNum - 1).getTerm() + averageCapitalPlusInterestBOInside.getTermInterval();
                    averageCapitalPlusInterestBOInside.setTerm(term);
                    //"sheet-等额本息"次数
                    actualLimitNum++;
                    break;
                }
            }else if(i == limitTime){
                pricingDate = localDateRepricing.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                averageCapitalPlusInterestBOInside.setPricingDate(pricingDate);
                //等额本息汇总:定价日期最后一个
                summaryBO.setPricingEndDate(pricingDate);
                //期限间隔
                averageCapitalPlusInterestBOInside.setTermInterval((int)localDateInit.until(localDateRepricing, ChronoUnit.DAYS));
                //期限
                Integer term = repricingDateList.get(actualLimitNum - 1).getTerm() + averageCapitalPlusInterestBOInside.getTermInterval();
                averageCapitalPlusInterestBOInside.setTerm(term);
                //"sheet-等额本息"次数
                actualLimitNum++;
            }
        }

    }

    /**
     * 第1步
     * 初始化基本信息
     */
    private void calculateInitActualBasicInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                     List<EcardFtpAverageCapitalPlusInterestBO> basicList){
        EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBO = new EcardFtpAverageCapitalPlusInterestBO();
        //业务日期/业务起始日
        averageCapitalPlusInterestBO.setBusinessDate(summaryBO.getBusinessBeginDate());
        //实际本金余额
        averageCapitalPlusInterestBO.setActualPrincipalBalance(summaryBO.getPrincipal());
        //实际现金流
        averageCapitalPlusInterestBO.setActualCashFlow(new BigDecimal(0));
        //实际利息流
        averageCapitalPlusInterestBO.setActualInterestFlow(new BigDecimal(0));
        //实际次数
        averageCapitalPlusInterestBO.setActualTimes(0);
        //实际期限间隔
        averageCapitalPlusInterestBO.setActualTermInterval(0);
        //实际期限
        averageCapitalPlusInterestBO.setActualTerm(0);
        //余额累计
        averageCapitalPlusInterestBO.setActualBalanceAccumulation(new BigDecimal(0));
        //实际每期贷款利率
        averageCapitalPlusInterestBO.setActualRateFlow(new BigDecimal(0));
        //实际每月还本付息金额
        averageCapitalPlusInterestBO.setActualRepayCapitalInterest(new BigDecimal(0));

        //TODO 上下分别两部分初始化

        //定价日期/业务起始日
        averageCapitalPlusInterestBO.setPricingDate(summaryBO.getBusinessBeginDate());
        //本金余额
        averageCapitalPlusInterestBO.setPrincipalBalance(summaryBO.getPrincipal());
        //现金流
        averageCapitalPlusInterestBO.setCashFlow(new BigDecimal(0));
        //利息流
        averageCapitalPlusInterestBO.setInterestFlow(new BigDecimal(0));
        //次数
        averageCapitalPlusInterestBO.setTimes(0);
        //期限间隔
        averageCapitalPlusInterestBO.setTermInterval(0);
        //期限
        averageCapitalPlusInterestBO.setTerm(0);
        //每期贷款利率
        averageCapitalPlusInterestBO.setRateFlow(new BigDecimal(0));
        //每月还本付息金额
        averageCapitalPlusInterestBO.setRepayCapitalInterest(new BigDecimal(0));

        //TODO 其他字段初始化

        //利率
        averageCapitalPlusInterestBO.setInterestRate(new BigDecimal(0));
        //现金流cashFlow * 期限term
        averageCapitalPlusInterestBO.setCalculateVal01(new BigDecimal(0));
        //现金流cashFlow * 期限term *利率interestRate
        averageCapitalPlusInterestBO.setCalculateVal02(new BigDecimal(0));
        //上限期限
        averageCapitalPlusInterestBO.setConfigUpperDay(0);
        //下限期限
        averageCapitalPlusInterestBO.setConfigUnderDay(0);
        //上限收益率
        averageCapitalPlusInterestBO.setConfigUpperRate(new BigDecimal(0));
        //下限收益率
        averageCapitalPlusInterestBO.setConfigUnderRate(new BigDecimal(0));

        basicList.add(averageCapitalPlusInterestBO);

    }


    /**
     * 第4步:等额本息
     * 计算实际本金余额、实际现金流、实际利息流、余额累计
     */
    private void calculateInterestActualAmountInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                          List<EcardFtpAverageCapitalPlusInterestBO> actualAmountInfoList){


        //现金流/业务到期日(直接取业务到期日)
        String cashFlowMaturityDate = summaryBO.getCashFlowMaturityDate();
        LocalDate localCashFlowMaturityDate = LocalDate.parse(cashFlowMaturityDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //每期还款额
        BigDecimal repaymentAmount = summaryBO.getRepaymentAmount();

        //余额累计汇总值
        BigDecimal balanceAccumulation = summaryBO.getBalanceAccumulation();

        //计算利率的次方值
        int actualPowNum = summaryBO.getActualPowNum();

        //期数:计算实际相关字段的总条数
        int limitTime = summaryBO.getActualTotalNum();

        //实际本金余额
        BigDecimal corpusLeft = summaryBO.getPrincipal();
        //利率
        BigDecimal rate = summaryBO.getRate();

        //实际本金余额
        BigDecimal corpusLeftMon = corpusLeft;
        //实际每期贷款利率
        BigDecimal ratePow = ((rate.divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)).add(new BigDecimal(1))).pow(actualPowNum).setScale(16,BigDecimal.ROUND_HALF_UP);
        //实际每月还本付息金额
        BigDecimal capMon = corpusLeft.multiply(rate.divide(new BigDecimal(12),16,BigDecimal.ROUND_HALF_UP)).multiply(ratePow).divide(ratePow.subtract(new BigDecimal(1)),2,BigDecimal.ROUND_HALF_UP);
        //实际现金流
        BigDecimal corpusMon;
        //实际利息流
        BigDecimal restMon;

        for (int i = 1; i <= limitTime; i++) {

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOLast = actualAmountInfoList.get(i-1);
            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = actualAmountInfoList.get(i);

            //上一次的实际本金余额
            corpusLeftMon = averageCapitalPlusInterestBOLast.getActualPrincipalBalance();
            //实际利息流
            restMon = corpusLeftMon.multiply
                    (
                            rate
                                    //日期差值动态值
                                    .multiply(new BigDecimal(averageCapitalPlusInterestBOInside.getActualTermInterval()))
                    ).divide(new BigDecimal(360),16,BigDecimal.ROUND_HALF_UP)
                    .setScale(2,BigDecimal.ROUND_HALF_UP);

            String businessDate = averageCapitalPlusInterestBOInside.getBusinessDate();
            LocalDate localBusinessDate = LocalDate.parse(businessDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            if(localBusinessDate.isEqual(localCashFlowMaturityDate)){
                corpusMon = corpusLeftMon;
            }else{
                corpusMon = repaymentAmount.subtract(restMon);
            }

            //最后一期
            if (i == limitTime) {
                //(注意这里设置的此条的余额累计,否则为NULL)余额累计=上一条数据的实际本金余额*此条数据的实际期限间隔
                averageCapitalPlusInterestBOInside.setActualBalanceAccumulation(new BigDecimal(0));
            }

            //实际本金余额
            corpusLeftMon = corpusLeftMon.subtract(corpusMon).setScale(2,BigDecimal.ROUND_HALF_UP);
            //实际本金余额
            averageCapitalPlusInterestBOInside.setActualPrincipalBalance(corpusLeftMon);
            //实际每期贷款利率
            averageCapitalPlusInterestBOInside.setActualRateFlow(ratePow);
            //实际每月还本付息金额
            averageCapitalPlusInterestBOInside.setActualRepayCapitalInterest(capMon);
            //实际现金流
            averageCapitalPlusInterestBOInside.setActualCashFlow(corpusMon);
            //实际利息流
            averageCapitalPlusInterestBOInside.setActualInterestFlow(restMon);
            //(注意这里设置的是上一条的余额累计)余额累计=上一条数据的实际本金余额*此条数据的实际期限间隔
            averageCapitalPlusInterestBOLast.setActualBalanceAccumulation(
                    averageCapitalPlusInterestBOLast.getActualPrincipalBalance()
                            .multiply(new BigDecimal(averageCapitalPlusInterestBOInside.getActualTermInterval())));
            //等额本息汇总:余额累计汇总值
            balanceAccumulation = balanceAccumulation.add(averageCapitalPlusInterestBOLast.getActualBalanceAccumulation());

        }
        //等额本息汇总:余额累计汇总值
        summaryBO.setBalanceAccumulation(balanceAccumulation);



    }

    /**
     * 第4步:等额本金
     * 计算实际本金余额、余额累计
     */
    private void calculatePrincipalActualAmountInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                           List<EcardFtpAverageCapitalPlusInterestBO> actualAmountInfoList){
        //余额累计汇总值
        BigDecimal balanceAccumulation = summaryBO.getBalanceAccumulation();

        //还款额
        BigDecimal repaymentAmount = summaryBO.getRepaymentAmount();

        //期数:计算实际相关字段的总条数
        int limitTime = summaryBO.getActualTotalNum();
        for (int i = 1; i <= limitTime; i++) {

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOLast = actualAmountInfoList.get(i-1);
            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = actualAmountInfoList.get(i);

            //实际本金余额
            BigDecimal actualPrincipalLast;
            //不是最后一期
            if (i != limitTime) {
                //上一条实际本金余额
                BigDecimal principalLast = averageCapitalPlusInterestBOLast.getActualPrincipalBalance();

                if(principalLast.compareTo(repaymentAmount) > 0){
                    actualPrincipalLast = principalLast.subtract(repaymentAmount);
                }else{
                    actualPrincipalLast = new BigDecimal("0");
                }
                //实际本金余额
                averageCapitalPlusInterestBOInside.setActualPrincipalBalance(actualPrincipalLast);
            }
            //最后一期
            else{
                //实际本金余额
                averageCapitalPlusInterestBOInside.setActualPrincipalBalance(new BigDecimal("0"));
                //实际本金余额
                averageCapitalPlusInterestBOInside.setActualBalanceAccumulation(new BigDecimal("0"));
            }

            //(注意这里设置的是上一条的余额累计)余额累计=上一条数据的实际本金余额*此条数据的实际期限间隔
            averageCapitalPlusInterestBOLast.setActualBalanceAccumulation(
                    averageCapitalPlusInterestBOLast.getActualPrincipalBalance()
                            .multiply(new BigDecimal(averageCapitalPlusInterestBOInside.getActualTermInterval())));
            //等额本息汇总:余额累计汇总值
            balanceAccumulation = balanceAccumulation.add(averageCapitalPlusInterestBOLast.getActualBalanceAccumulation());
        }
        //等额本息汇总:余额累计汇总值
        summaryBO.setBalanceAccumulation(balanceAccumulation);

    }


    /**
     * 第2步
     * 计算业务日期及其日期间隔等
     */
    private void calculateBusinessDateInfo(EcardFtpAverageCapitalPlusInterestSummaryBO summaryBO,
                                                  List<EcardFtpAverageCapitalPlusInterestBO> businessDateList){


        //起始日
        LocalDate localDateInit = LocalDate.parse(summaryBO.getBusinessBeginDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //到期日
        LocalDate localDateFinally = LocalDate.parse(summaryBO.getBusinessEndDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        //还款频率
        int repaymentFrequency = summaryBO.getRepaymentFrequency();
        //期数:计算实际相关字段的总条数
        int limitTime = summaryBO.getActualTotalNum();

        LocalDate localDateNext = null;
        //"sheet-等额本息"次数
        int actualLimitNum = 1;
        boolean flag = true;
        for (int i = 1; i <= limitTime; i++) {
            if(flag){
                localDateNext = localDateInit.plusMonths(repaymentFrequency);
            }else{
                localDateNext = localDateNext.plusMonths(repaymentFrequency);
            }
            int localDateMonthNext = localDateNext.getMonth().getValue();
            if (localDateMonthNext != 2) {
                int localDateDayCurrent = localDateInit.getDayOfMonth();
                int localDateDayNext = localDateNext.getDayOfMonth();
                if(localDateDayCurrent > 30 && localDateDayNext == 30){
                    localDateNext = LocalDate.of(localDateNext.getYear(),localDateMonthNext + 1,localDateDayCurrent - localDateDayNext);
                }
                flag = true;
            } else {
                int localDateDayCurrent = localDateInit.getDayOfMonth();
                if (localDateDayCurrent > 28) {
                    int localDateDayNext = localDateNext.getDayOfMonth();
                    int difference = localDateDayCurrent - localDateDayNext;
                    int localDateYearNext = localDateNext.getYear();
                    if ((localDateYearNext % 4 == 0 && localDateYearNext % 100 != 0) || localDateYearNext % 400 == 0) {
                        if(difference > 0){
                            localDateNext = LocalDate.of(localDateYearNext,3,difference);
                        }
                    }else{
                        localDateNext = LocalDate.of(localDateYearNext,3,difference);
                    }
                    flag = false;
                }
            }

            EcardFtpAverageCapitalPlusInterestBO averageCapitalPlusInterestBOInside = new EcardFtpAverageCapitalPlusInterestBO();
            //实际次数
            averageCapitalPlusInterestBOInside.setActualTimes(actualLimitNum);
            //"sheet-等额本息"业务日期
            String actualBusinessDate;
            //最后一个日期值的处理
            if(i != limitTime){
                if(localDateNext.isBefore(localDateFinally)){
                    actualBusinessDate = localDateNext.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    averageCapitalPlusInterestBOInside.setBusinessDate(actualBusinessDate);
                    //实际期限间隔
                    averageCapitalPlusInterestBOInside.setActualTermInterval((int)localDateInit.until(localDateNext, ChronoUnit.DAYS));
                    //实际期限
                    Integer actualTerm = businessDateList.get(actualLimitNum - 1).getActualTerm() + averageCapitalPlusInterestBOInside.getActualTermInterval();
                    averageCapitalPlusInterestBOInside.setActualTerm(actualTerm);
                    businessDateList.add(averageCapitalPlusInterestBOInside);
                    //设置当前日期对象(用于下次日期的处理)
                    localDateInit = localDateNext;
                    //"sheet-等额本息"次数
                    actualLimitNum++;
                }else{
                    //如果计算得到的下一个日期localDateNext大于现金流到期日/业务到期日localDateFinally,那么取localDateFinally.
                    actualBusinessDate = localDateFinally.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    averageCapitalPlusInterestBOInside.setBusinessDate(actualBusinessDate);
                    //实际期限间隔
                    averageCapitalPlusInterestBOInside.setActualTermInterval((int)localDateInit.until(localDateFinally, ChronoUnit.DAYS));
                    //实际期限
                    Integer actualTerm = businessDateList.get(actualLimitNum - 1).getActualTerm() + averageCapitalPlusInterestBOInside.getActualTermInterval();
                    averageCapitalPlusInterestBOInside.setActualTerm(actualTerm);
                    businessDateList.add(averageCapitalPlusInterestBOInside);
                    //"sheet-等额本息"次数
                    actualLimitNum++;
                    break;
                }
            }else if(i == limitTime){
                actualBusinessDate = localDateFinally.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                averageCapitalPlusInterestBOInside.setBusinessDate(actualBusinessDate);
                //实际期限间隔
                averageCapitalPlusInterestBOInside.setActualTermInterval((int)localDateInit.until(localDateFinally, ChronoUnit.DAYS));
                //实际期限
                Integer actualTerm = businessDateList.get(actualLimitNum - 1).getActualTerm() + averageCapitalPlusInterestBOInside.getActualTermInterval();
                averageCapitalPlusInterestBOInside.setActualTerm(actualTerm);
                businessDateList.add(averageCapitalPlusInterestBOInside);
                //"sheet-等额本息"次数
                actualLimitNum++;
            }
        }


    }




}
